﻿using System;
using System.ComponentModel;
using System.Drawing;
using RaytracerLib;
using RaytracerLib.MathLib;
using RaytracerLib.Postprocessing.LightCorrector;
using RaytracerLib.Resamplers;
using RaytracerLib.Samplers;
using RaytracerLib.ShadowTesters;
using RaytracerLib.Attenuations;
using RaytracerLib.MathLib.Polynomials;
using RaytracerLib.MathLib.RootFinders;
using RaytracerLib.Renderers;

namespace Raytracer.PropertyGridDecorators
{
    public class RenderOptionsProperties
    {
        private RenderOptions m_render_options;

        public RenderOptionsProperties(RenderOptions a_render_options)
        {
            m_render_options = a_render_options;
        }

        [DisplayName("Break on intersection ID")]
        [Category(Categories.DEBUG)]
        public long DebugBreakIntersectionID
        {
            get
            {
                return m_render_options.DebugBreakIntersectionID;
            }
            set
            {
                m_render_options.DebugBreakIntersectionID = value;
            }
        }

        [DisplayName("Pixel X")]
        [Category(Categories.DEBUG)]
        [TypeConverter(typeof(DoubleConverter))]
        public double DebugPixelX
        {
            get
            {
                return m_render_options.DebugPixelX;
            }
            set
            {
                m_render_options.DebugPixelX = value;
            }
        }

        [DisplayName("Pixel Y")]
        [Category(Categories.DEBUG)]
        [TypeConverter(typeof(DoubleConverter))]
        public double DebugPixelY
        {
            get
            {
                return m_render_options.DebugPixelY;
            }
            set
            {
                m_render_options.DebugPixelY = value;
            }
        }

        [Category(Categories.RENDER)]
        public bool Parallel
        {
            get
            {
                return m_render_options.Parallel;
            }
            set
            {
                m_render_options.Parallel = value;
            }
        }

        [Category(Categories.DEBUG)]
        [DisplayName("High priority")]
        public bool HighPriority
        {
            get
            {
                return m_render_options.HighPriority;
            }
            set
            {
                m_render_options.HighPriority = value;
            }
        }

        [Category(Categories.MATH)]
        [DisplayName("Polynomial solve method")]
        public PolynomialSolveMethod PolynomialSolveMethod
        {
            get
            {
                return m_render_options.PolynomialSolveMethod;
            }
            set
            {
                m_render_options.PolynomialSolveMethod = value;
            }
        }

        [Category(Categories.MATH)]
        [DisplayName("Root finding method")]
        public RootFindingMethod RootFindingMethod
        {
            get
            {
                return m_render_options.RootFindingMethod;
            }
            set
            {
                m_render_options.RootFindingMethod = value;
            }
        }

        [Category(Categories.ENVIRONMENT)]
        [DisplayName("Light speed")]
        public double LightSpeed
        {
            get
            {
                return m_render_options.LightSpeed;
            }
            set
            {
                m_render_options.LightSpeed = value;
            }
        }

        [Category(Categories.RENDER)]
        [DisplayName("Shadow test method")]
        public ShadowTestMethod ShadowTestMethod
        {
            get
            {
                return m_render_options.ShadowTestMethod;
            }
            set
            {
                m_render_options.ShadowTestMethod = value;
            }
        }

        [DisplayName("Ambient system color")]
        [Category(Categories.ENVIRONMENT)]
        public Color AmbientSystemColor
        {
            get
            {
                return m_render_options.AmbientColor.SystemColor;
            }
            set
            {
                m_render_options.AmbientColor = new ColorFloat(value);
            }
        }

        [DisplayName("Ambient color")]
        [Category(Categories.ENVIRONMENT)]
        [TypeConverter(typeof(ColorFloatConverter))]
        public ColorFloatProperties AmbientColor
        {
            get
            {
                return new ColorFloatProperties(
                    () => m_render_options.AmbientColor,
                    (c) => m_render_options.AmbientColor = c);
            }
            set
            {
                m_render_options.AmbientColor = value.ToColorFloat();
            }
        }

        [DisplayName("Environment refraction indice")]
        [Category(Categories.ENVIRONMENT)]
        [TypeConverter(typeof(DoubleConverter))]
        public double EnvironmentRefractionIndice
        {
            get
            {
                return m_render_options.EnvironmentRefractionIndice;
            }
            set
            {
                m_render_options.EnvironmentRefractionIndice = value;
            }
        }

        [DisplayName("Environment attenuation method")]
        [Category(Categories.ENVIRONMENT)]
        public AttenuationMethod EnvironmentAttenuationMethod
        {
            get
            {
                if (m_render_options.EnvironmentAttenuation == null)
                    return AttenuationMethod.None;
                else if (m_render_options.EnvironmentAttenuation is PolynomialAttenuation)
                    return AttenuationMethod.Polynomial;
                else if (m_render_options.EnvironmentAttenuation is ExponentalAttenuation)
                    return AttenuationMethod.Exponental;
                else
                    throw new InvalidOperationException();
            }
            set
            {
                m_render_options.EnvironmentAttenuation = Attenuation.Create(value);
            }
        }

        [DisplayName("Environment attenuation")]
        [Category(Categories.ENVIRONMENT)]
        [TypeConverter(typeof(AttenuationConverter))]
        public AttenuationProperties EnvironmentAttenuation
        {
            get
            {
                if (m_render_options.EnvironmentAttenuation == null)
                    return null;
                else if (m_render_options.EnvironmentAttenuation is ExponentalAttenuation)
                {
                    return new ExponentalAttenuationProperties(
                        m_render_options.EnvironmentAttenuation as ExponentalAttenuation);
                }
                else if (m_render_options.EnvironmentAttenuation is PolynomialAttenuation)
                {
                    return new PolynomialAttenuationProperties(
                        m_render_options.EnvironmentAttenuation as PolynomialAttenuation);
                }
                else
                    throw new NotImplementedException();
            }
        }

        [Category(Categories.RENDER)]
        [TypeConverter(typeof(RendererConverter))]
        public RendererProperties Renderer
        {
            get
            {
                if (m_render_options.Renderer is SamplesVisualizerRenderer)
                {
                    return new SamplesVisualizerRendererProperties(
                        m_render_options.Renderer as SamplesVisualizerRenderer);
                }
                else if (m_render_options.Renderer is SamplesPeriodogramRenderer)
                {
                    return new SamplesPeriodogramRendererProperties(
                        m_render_options.Renderer as SamplesPeriodogramRenderer);
                }
                else
                    return new RendererProperties(m_render_options.Renderer);
            }
        }

        [DisplayName("Renderer type")]
        [Category(Categories.RENDER)]
        public RaytracerLib.Renderers.RendererType RendererType
        {
            get
            {
                return m_render_options.Renderer.RendererType;
            }
            set
            {
                m_render_options.Renderer = RaytracerLib.Renderers.Renderer.Create(value);
            }
        }
    }
}